package com.example.demo.juc;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

/**
 * 采用Fork/Join来异步计算1+2+3+…+10000的结果
 */
public class ForkJoinTest {
//    static final class SumTask extends RecursiveTask<Long> {
//        private static final long serialVersionUID = 1L;
//        final long start;//最开始计算的数
//        final long end;//最后计算的数
//
//        public SumTask(long start, long end) {
//            this.start = start;
//            this.end = end;
//        }
//
//        @Override
//        protected Long compute() {
//            //如果计算量小于1000，那么直接计算
//            if(end-start<1000){
//                System.out.println(Thread.currentThread().getName() + "开始执行："+start+"-"+end);
//                long sum = 0;
//                for(long i=start;i<=end;i++){
//                    sum += i;
//                }
//                return sum;
//            }
//            //如果计算量大于1000，那么拆分为两个任务
//            SumTask task1 = new SumTask(start,(start+end)/2);
//            SumTask task2 = new SumTask((start+end)/2+1,end);
//            //执行任务
//            task1.fork();
//            task2.fork();
//            //获取任务执行结果
//            return task1.join()+task2.join();
//        };
//    }
//
//
//    public static void main(String[] args) throws ExecutionException, InterruptedException {
//        ForkJoinPool pool = new ForkJoinPool();
//        ForkJoinTask<Long> task = new SumTask(1,10000);
//        pool.submit(task);
//        System.out.println(task.get());
//    }

    /**
     * 斐波那契数列
     */
    static class Fibonacci extends RecursiveTask<Long> {
        private static final long serialVersionUID = 1L;
        final Long n;
        public Fibonacci(Long n) {
            this.n = n;
        }

        @Override
        protected Long compute() {
            if (n <= 1) {
                return n;
            }
            Fibonacci f1 = new Fibonacci(n - 1);
            f1.fork();
            Fibonacci f2 = new Fibonacci(n - 2);
            return f2.compute() + f1.join();
        }
    }

    public static void main(String[] args) {
        ForkJoinPool pool = new ForkJoinPool();
        Fibonacci fibonacci = new Fibonacci(10L);
        long startTime = System.currentTimeMillis();
        Long result = pool.invoke(fibonacci);
        long endTime = System.currentTimeMillis();
        System.out.println("result = " + result + ", time = " + (endTime - startTime));
    }
}
